﻿namespace CookieTerm
{
    using System;
    using System.Net;
    using System.Net.Sockets;
    using Routrek.SSHC;

    public class SshTerminal : Terminal, ISSHConnectionEventReceiver, ISSHChannelEventReceiver
    {
        SSHConnection connection;
        SSHChannel channel;

        public string UserName { get; set; }
        public string Password { get; set; }

        public SshTerminal()
        {
        }

        protected override void AfterConnected()
        {
            SSHConnectionParameter parameter = new SSHConnectionParameter();
            parameter.UserName = this.UserName;
            parameter.Password = this.Password;
            parameter.Protocol = SSHProtocol.SSH1;
            parameter.AuthenticationType = AuthenticationType.Password;
            parameter.PreferableCipherAlgorithms = new CipherAlgorithm[] { CipherAlgorithm.Blowfish, CipherAlgorithm.TripleDES };

            try
            {
                this.connection = SSHConnection.Connect(parameter, this, this.Socket);
            }
            catch (Exception)
            {
                if (this.Socket != null && this.Socket.Connected)
                {
                    this.Socket.Shutdown(SocketShutdown.Both);
                    this.Socket.Close();
                }

                throw;
            }
        }

        public override void Send(byte[] data)
        {
            try
            {
                this.channel.Transmit(data);
            }
            catch (SocketException)
            {
                Disconnect();
            }
        }

        public override void Receive()
        {
            try
            {
                this.channel = this.connection.OpenShell(this);
            }
            catch (SocketException)
            {
                Disconnect();
            }
        }

        public void OnData(byte[] data, int offset, int length)
        {
            byte[] buffer = new byte[length];
            Array.Copy(data, offset, buffer, 0, length);
            InvokeOnDataAvailable(new DataAvailableEventArgs(buffer));
        }

        public void OnExtendedData(int type, byte[] data)
        {
        }

        public void OnChannelClosed()
        {
            this.connection.Disconnect("");
        }

        public void OnChannelEOF()
        {
            this.channel.Close();
        }

        public void OnChannelError(Exception error, string msg)
        {
            Disconnect();
        }

        public void OnChannelReady()
        {
        }

        public void OnMiscPacket(byte packet_type, byte[] data, int offset, int length)
        {
        }

        public void OnDebugMessage(bool always_display, byte[] msg)
        {
        }

        public void OnIgnoreMessage(byte[] msg)
        {
        }

        public void OnUnknownMessage(byte type, byte[] data)
        {
        }

        public void OnError(Exception error, string msg)
        {
            Disconnect();
        }

        public void OnConnectionClosed()
        {
            Disconnect();
        }

        public void OnAuthenticationPrompt(string[] prompts)
        {
            throw new NotImplementedException();
        }

        public PortForwardingCheckResult CheckPortForwardingRequest(string remote_host, int remote_port, string originator_ip, int originator_port)
        {
            return new PortForwardingCheckResult()
            {
                allowed = false
            };
        }

        public void EstablishPortforwarding(ISSHChannelEventReceiver receiver, SSHChannel channel)
        {
        }
    }
}